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.