In the previous lessons, all the metrics and traces you sent were with the aim to have a visual representation. There is still a need for ordinary text information. You’re probably used to reading logs from your users, you may have generated some logs and sent them through a feedback form in your app.
OpenTelemetry can make this easier to collect, and you can still benefit from the visual graphs of traces and metrics for your logs.
To get started, open the starter project for the lesson. The project has the implementation for OTelLogs and the setup needed to connect the log exporter to Grafana, just as you did before with metrics and spans.
Add your token and endpoint to the Common.swift file so the app can connect to your server.
Sending a log works almost the same as sending a metric. Open OTelLogs.swift and add this at the end of the class:
public func sendLog(
scope: String,
message: String
) {
let openTelemetry = OpenTelemetry.instance
let otelLogger = openTelemetry.loggerProvider.loggerBuilder(instrumentationScopeName: scope).setEventDomain("Device").build()
let log = otelLogger.logRecordBuilder()
.setBody(.string(message))
log.emit()
}
There is nothing here that you haven’t seen before with metrics. You create a logger from the loggerBuilder method. The setBody() creates an instance of the log itself, then finally calling emit() to send the log.
For convenience, create a class method for sendLog(::):
public class func sendLog(
scope: String,
message: String
) {
shared.sendLog(
scope: scope,
message: message)
}
Go to TheMetStore.swift and add log at the end of fetchObjects(for:):
OTelLogs.sendLog(
scope: "TheMet-Logs",
message: "Searched for \(queryTerm), found \(objects.count) objects")
Build and run the app, you can search a couple of times for different keywords.
Open your Grafana portal and open “Logs”. You’ll find “TheMet” as one of the services.
The 'Logs' portal showing the 'TheMet' service with the log we just entered
Click on the “Show logs” button to see the logs better. Then click on the “Table” tab on the right.
The 'Table' of the 'Log' showing the 'Time' and the 'Line' of each log
The graph on the top represents the amount of logs over time. The checkboxes on the left allow you to choose which fields to show in the table. Feel free to add a few.
This log you sent is meant to be an example, it’s not meant to be used like print(). That will make your logs list messy and harder to understand. Feel free to remove it.
Another way to make logs easy to understand is to give them context beside the content in the log itself. You can connect logs to spans almost the same way you connect spans together.
Change sendLog to the following:
public func sendLog(
scope: String,
message: String,
span: (any Span)? = nil
) {
let openTelemetry = OpenTelemetry.instance
let otelLogger = openTelemetry.loggerProvider.loggerBuilder(instrumentationScopeName: scope).setEventDomain("Device").build()
let log = otelLogger.logRecordBuilder()
.setBody(.string(message))
if let span {
_ = log.setSpanContext(span.context)
}
log.emit()
}
Go back to TheMetStore.swift and move the call to send the log before ending the span, and add the span as a parameter in the function call:
OTelLogs.sendLog(
scope: "TheMet-Logs",
message: "Searched for \(queryTerm), found \(objects.count) objects",
span: span)
Build and run the app. Open Logs on Grafana, and you’ll see the logs reachable from there. A new field called “span_id” will appear in the scrollable “Fields” list on the left.
Go to “Traces” and open the main span for “fetchObjects”. Clicking the button “Logs for this span” will show only the logs connected to this span.
The main span for 'fetchObjects' with the 'Logs for this span' button
You can have multiple logs attached to a span.
See forum comments
This content was released on Oct 24 2025. The official support period is 6-months
from this date.
In this section, you’ll learn about Logging with OpenTelemetry
Download course materials from Github
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress,
bookmark, personalise your learner profile and more!
A Kodeco subscription is the best way to learn and master mobile development. Learn iOS, Swift, Android, Kotlin, Flutter and Dart development and unlock our massive catalog of 50+ books and 4,000+ videos.