Skip to content

Commit 1785645

Browse files
committed
+docs,sample Include Sample Dinner system and document with images
1 parent b8021de commit 1785645

21 files changed

+612
-127
lines changed

Samples/Dinner/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.build
2+
Package.resolved

Samples/Dinner/Package.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// swift-tools-version:5.3
2+
import PackageDescription
3+
4+
let package = Package(
5+
name: "onboarding",
6+
platforms: [
7+
.macOS("14.0.0"),
8+
],
9+
products: [
10+
.executable(name: "onboarding", targets: ["Onboarding"]),
11+
],
12+
dependencies: [
13+
// This example uses the following tracer implementation:
14+
.package(url: "https://github.com/slashmo/opentelemetry-swift", .branch("main")),
15+
.package(url: "https://github.com/apple/swift-log.git", from: "1.0.0"),
16+
],
17+
targets: [
18+
.target(name: "Onboarding", dependencies: [
19+
.product(name: "OpenTelemetry", package: "opentelemetry-swift"),
20+
.product(name: "OtlpGRPCSpanExporting", package: "opentelemetry-swift"),
21+
]),
22+
]
23+
)

Samples/Dinner/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
## Tracing Dinner Sample App
2+
3+
In order to try this sample app, and visualize traces it produces, you should first run docker-compose in order
4+
to launch a docker containers which host a Zipkin UI and collector:
5+
6+
```
7+
# cd Samples/Dinner
8+
9+
docker-compose -f docker/docker-compose.yaml up --build
10+
```
11+
12+
and then run the sample app which will produce a number of traces:
13+
14+
```
15+
swift run -c release
16+
```
17+
18+
Refer to the "Trace Your Application" guide in the documentation to learn more about how to interpret this sample.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift OpenTelemetry open source project
4+
//
5+
// Copyright (c) 2021 Moritz Lang and the Swift OpenTelemetry project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
//
10+
// SPDX-License-Identifier: Apache-2.0
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
func sleep(for duration: ContinuousClock.Duration) async {
15+
try? await Task.sleep(until: ContinuousClock.now + duration, clock: .continuous)
16+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift OpenTelemetry open source project
4+
//
5+
// Copyright (c) 2021 Moritz Lang and the Swift OpenTelemetry project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
//
10+
// SPDX-License-Identifier: Apache-2.0
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
import Tracing
15+
16+
func makeDinner() async throws -> Meal {
17+
try await InstrumentationSystem.tracer.withSpan("makeDinner") { _ in
18+
await sleep(for: .milliseconds(200))
19+
20+
async let veggies = try chopVegetables()
21+
async let meat = marinateMeat()
22+
async let oven = preheatOven(temperature: 350)
23+
// ...
24+
return try await cook(veggies, meat, oven)
25+
}
26+
}
27+
28+
func chopVegetables() async throws -> [Vegetable] {
29+
try await otelChopping1.tracer().withSpan("chopVegetables") { _ in
30+
// Chop the vegetables...!
31+
//
32+
// However, since chopping is a very difficult operation,
33+
// one chopping task can be performed at the same time on a single service!
34+
// (Imagine that... we cannot parallelize these two tasks, and need to involve another service).
35+
async let carrot = try chop(.carrot, tracer: otelChopping1.tracer())
36+
async let potato = try chop(.potato, tracer: otelChopping2.tracer())
37+
return try await [carrot, potato]
38+
}
39+
}
40+
41+
func chop(_ vegetable: Vegetable, tracer: any Tracer) async throws -> Vegetable {
42+
await tracer.withSpan("chop-\(vegetable)") { _ in
43+
await sleep(for: .seconds(5))
44+
// ...
45+
return vegetable // "chopped"
46+
}
47+
}
48+
49+
func marinateMeat() async -> Meat {
50+
await sleep(for: .milliseconds(620))
51+
52+
return await InstrumentationSystem.tracer.withSpan("marinateMeat") { _ in
53+
await sleep(for: .seconds(3))
54+
// ...
55+
return Meat()
56+
}
57+
}
58+
59+
func preheatOven(temperature: Int) async -> Oven {
60+
await InstrumentationSystem.tracer.withSpan("preheatOven") { _ in
61+
// ...
62+
await sleep(for: .seconds(6))
63+
return Oven()
64+
}
65+
}
66+
67+
func cook(_: Any, _: Any, _: Any) async -> Meal {
68+
await InstrumentationSystem.tracer.withSpan("cook") { span in
69+
span.addEvent("children-asking-if-done-already")
70+
await sleep(for: .seconds(3))
71+
span.addEvent("children-asking-if-done-already-again")
72+
await sleep(for: .seconds(2))
73+
// ...
74+
return Meal()
75+
}
76+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift OpenTelemetry open source project
4+
//
5+
// Copyright (c) 2021 Moritz Lang and the Swift OpenTelemetry project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
//
10+
// SPDX-License-Identifier: Apache-2.0
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
struct Meal: Sendable {}
15+
struct Meat: Sendable {}
16+
struct Oven: Sendable {}
17+
enum Vegetable: Sendable {
18+
case potato
19+
case carrot
20+
}
21+
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift OpenTelemetry open source project
4+
//
5+
// Copyright (c) 2021 Moritz Lang and the Swift OpenTelemetry project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
//
10+
// SPDX-License-Identifier: Apache-2.0
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
import Logging
15+
import NIO
16+
import OpenTelemetry
17+
import OtlpGRPCSpanExporting
18+
import Tracing
19+
20+
// ==== ----------------------------------------------------------------------------------------------------------------
21+
22+
let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
23+
24+
LoggingSystem.bootstrap { label in
25+
var handler = StreamLogHandler.standardOutput(label: label)
26+
handler.logLevel = .trace
27+
return handler
28+
}
29+
30+
// ==== ----------------------------------------------------------------------------------------------------------------
31+
// MARK: - Configure OTel
32+
33+
let exporter = OtlpGRPCSpanExporter(config: OtlpGRPCSpanExporter.Config(eventLoopGroup: group))
34+
let processor = OTel.SimpleSpanProcessor(exportingTo: exporter)
35+
let otel = OTel(serviceName: "DinnerService", eventLoopGroup: group, processor: processor)
36+
37+
let otelChopping1 = OTel(serviceName: "ChoppingService-1", eventLoopGroup: group, processor: processor)
38+
let otelChopping2 = OTel(serviceName: "ChoppingService-2", eventLoopGroup: group, processor: processor)
39+
40+
// First start `OTel`, then bootstrap the instrumentation system.
41+
// This makes sure that all components are ready to begin handling spans.
42+
try otel.start().wait()
43+
try otelChopping1.start().wait()
44+
try otelChopping2.start().wait()
45+
46+
// By bootstrapping the instrumentation system, our dependencies
47+
// compatible with "Swift Distributed Tracing" will also automatically
48+
// use the "OpenTelemetry Swift" Tracer 🚀.
49+
InstrumentationSystem.bootstrap(otel.tracer())
50+
51+
// ==== ----------------------------------------------------------------------------------------------------------------
52+
// MARK: - Run the sample app
53+
54+
let dinner = try await makeDinner()
55+
56+
// ==== ----------------------------------------------------------------------------------------------------------------
57+
// MARK: - Shutdown
58+
59+
// Wait a second to let the exporter finish before shutting down.
60+
sleep(2)
61+
62+
try otel.shutdown().wait()
63+
try group.syncShutdownGracefully()
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
receivers:
2+
otlp:
3+
protocols:
4+
grpc:
5+
endpoint: otel-collector:4317
6+
7+
exporters:
8+
logging:
9+
logLevel: debug
10+
11+
jaeger:
12+
endpoint: "jaeger:14250"
13+
tls:
14+
insecure: true
15+
16+
zipkin:
17+
endpoint: "http://zipkin:9411/api/v2/spans"
18+
19+
20+
service:
21+
pipelines:
22+
traces:
23+
receivers: otlp
24+
exporters: [logging, jaeger, zipkin]
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
version: '3'
2+
services:
3+
otel-collector:
4+
image: otel/opentelemetry-collector-contrib:latest
5+
command: ["--config=/etc/config.yaml"]
6+
volumes:
7+
- ./collector-config.yaml:/etc/config.yaml
8+
ports:
9+
- "4317:4317"
10+
networks: [exporter]
11+
depends_on: [zipkin, jaeger]
12+
13+
zipkin:
14+
image: openzipkin/zipkin:latest
15+
ports:
16+
- "9411:9411"
17+
networks: [exporter]
18+
19+
jaeger:
20+
image: jaegertracing/all-in-one
21+
ports:
22+
- "16686:16686"
23+
networks: [exporter]
24+
25+
networks:
26+
exporter:

0 commit comments

Comments
 (0)