Getting Started

Get telemetry for your app in less than 5 minutes!

This page will show you how to get started with OpenTelemetry in Swift.

You will learn how you can instrument a simple application, in such a way that traces are emitted to the console.

Prerequisites

Ensure that you have the following installed locally:

Example Application

The following example uses a basic Vapor application. If you are not using Vapor, that’s OK — you can use OpenTelemetry Swift with any Swift application, no matter if they run on a server or on an iOS device.

For more examples, see examples.

Dependencies

To begin, create a file called Package.swift in a new directory with the following content:

// swift-tools-version:5.9 import PackageDescription let package = Package( name: "dice-server", platforms: [ .macOS(.v13) ], dependencies: [ .package(url: "https://github.com/vapor/vapor.git", from: "4.83.1") ], targets: [ .executableTarget( name: "DiceApp", dependencies: [ .product(name: "Vapor", package: "vapor") ], path: "." ) ] )

Create and launch an HTTP Server

In the same folder, create a file called main.swift and add the following code to the file:

import Vapor @main enum Entrypoint { static func main() async throws { let app = try Application(.detect()) defer { app.shutdown() } app.get("rolldice") { req in let result = Int.random(in: 1..<7) return result } try app.run() } }

Build and run the application with the following command, then open http://localhost:8080/rolldice in your web browser to ensure it is working.

$ swift run Building for debugging... Build complete! (0.31s) 2023-10-04T17:16:13+0200 notice codes.vapor.application : [Vapor] Server starting on http://127.0.0.1:8080

Instrumentation

To add OpenTelemetry to your application, update the Package.swift with the following additional dependencies:

// swift-tools-version:5.9 import PackageDescription let package = Package( name: "dice-server", platforms: [ .macOS(.v13) ], dependencies: [ .package(url: "https://github.com/vapor/vapor.git", from: "4.83.1"), .package(url: "https://github.com/open-telemetry/opentelemetry-swift", from: "1.0.0"), ], targets: [ .executableTarget( name: "DiceApp", dependencies: [ .product(name: "Vapor", package: "vapor"), .product(name: "OpenTelemetryApi", package: "opentelemetry-swift"), .product(name: "OpenTelemetrySdk", package: "opentelemetry-swift"), .product(name: "StdoutExporter", package: "opentelemetry-swift"), .product(name: "ResourceExtension", package: "opentelemetry-swift"), ], path: "." ) ] )

Update the main.swift file with code to initialize a tracer and to emit spans when the rolldice request handler is called:

import Vapor import OpenTelemetryApi import OpenTelemetrySdk import StdoutExporter import ResourceExtension @main enum Entrypoint { static func main() async throws { let spanExporter = StdoutExporter(); let spanProcessor = SimpleSpanProcessor(spanExporter: spanExporter) let resources = DefaultResources().get() let instrumentationScopeName = "DiceServer" let instrumentationScopeVersion = "semver:0.1.0" OpenTelemetry.registerTracerProvider(tracerProvider: TracerProviderBuilder() .add(spanProcessor: spanProcessor) .with(resource: resources) .build() ) let tracer = OpenTelemetry.instance.tracerProvider.get(instrumentationName: instrumentationScopeName, instrumentationVersion: instrumentationScopeVersion) as! TracerSdk let app = try Application(.detect()) defer { app.shutdown() } app.get("rolldice") { req in let span = tracer.spanBuilder(spanName: "GET /rolldice").setSpanKind(spanKind: .client).startSpan() let result = Int.random(in: 1..<7) span.end(); return result } try app.run() } }

Start your server again:

swift run

When you send a request to the server at http://localhost:8080/rolldice, you’ll see a span being emitted to the console (output is pretty printed for convenience):

{ "attributes": {}, "duration": 2.70605087280273e-5, "parentSpanId": "0000000000000000", "span": "GET /rolldice", "spanId": "635455eb236a1592", "spanKind": "client", "start": 718126321.210727, "traceFlags": { "sampled": true }, "traceId": "c751f7af0586dac8ef3607c6fc128884", "traceState": { "entries": [] } }

Next Steps

Enrich your instrumentation generated automatically with manual instrumentation of your own codebase. This gets you customized observability data.

Take a look at available instrumentation libraries that generate telemetry data for popular frameworks and libraries.