Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Docs] Combined initial documentation work #121

Merged
merged 10 commits into from
May 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Documentation landing page

This documentation target exists only to serve as a landing page for self-hosted documentation.
29 changes: 29 additions & 0 deletions Docs/SwiftDistributedTracing/Docs.docc/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# ``SwiftDistributedTracing``

A Distributed Tracing API for Swift.

## Overview

This is a collection of Swift libraries enabling the instrumentation of server side applications using tools such as tracers. Our goal is to provide a common foundation that allows to freely choose how to instrument systems with minimal changes to your actual code.

While Swift Distributed Tracing allows building all kinds of _instruments_, which can co-exist in applications transparently, its primary use is instrumenting multi-threaded and distributed systems with Distributed Traces.

### Quickstart Guides

We provide a number of guides aimed at getting your started with tracing your systems and have prepared them from three "angles":
ktoso marked this conversation as resolved.
Show resolved Hide resolved

1. **Application developers** who create server-side applications
* please refer to the <doc:TraceYourApplication> guide.
2. **Library/Framework developers** who provide building blocks to create these applications
* please refer to the <doc:InstrumentYourLibrary> guide.
3. **Instrument developers** who provide tools to collect distributed metadata about your application
* please refer to the <doc:ImplementATracer> guide.


## Topics

### Guides

- <doc:TraceYourApplication>
- <doc:InstrumentYourLibrary>
- <doc:ImplementATracer>
19 changes: 19 additions & 0 deletions Docs/SwiftDistributedTracing/empty.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift Distributed Tracing open source project
//
// Copyright (c) 2020-2021 Apple Inc. and the Swift Distributed Tracing project
ktoso marked this conversation as resolved.
Show resolved Hide resolved
// authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //
// This module is left purposefully empty of any source files, as it serves
// only as a "landing page" for the documentation. This is in-place until docc
// gains the ability to support package-wide documentation.
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //
2 changes: 2 additions & 0 deletions Samples/Dinner/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.build
Package.resolved
23 changes: 23 additions & 0 deletions Samples/Dinner/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// swift-tools-version:5.3
import PackageDescription

let package = Package(
name: "onboarding",
platforms: [
.macOS("13.0.0"),
],
products: [
.executable(name: "onboarding", targets: ["Onboarding"]),
],
dependencies: [
// This example uses the following tracer implementation:
.package(url: "https://github.com/slashmo/swift-otel", .branch("main")),
.package(url: "https://github.com/apple/swift-log.git", from: "1.5.0"),
],
targets: [
.target(name: "Onboarding", dependencies: [
.product(name: "OpenTelemetry", package: "swift-otel"),
.product(name: "OtlpGRPCSpanExporting", package: "swift-otel"),
]),
]
)
18 changes: 18 additions & 0 deletions Samples/Dinner/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
## Tracing Dinner Sample App

In order to try this sample app, and visualize traces it produces, you should first run `docker-compose` in order
to launch a docker containers which host a Zipkin UI and collector:

```
# cd Samples/Dinner

docker-compose -f docker/docker-compose.yaml up --build
```

and then run the sample app which will produce a number of traces:

```
swift run -c release
```

Refer to the "Trace Your Application" guide in the documentation to learn more about how to interpret this sample.
ktoso marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this link to "Trace Your Application" guide directly from here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah okey

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heh actually such link is not possible unless as a <a href... I can do those later, I don't know the URL to point to unless we have something published on the package index.

29 changes: 29 additions & 0 deletions Samples/Dinner/Sources/Onboarding/Clock+Extensions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift Distributed Tracing open source project
//
// Copyright (c) 2020-2023 Apple Inc. and the Swift Distributed Tracing project
// authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift OpenTelemetry open source project
//
// Copyright (c) 2021 Moritz Lang and the Swift OpenTelemetry project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

func sleep(for duration: ContinuousClock.Duration) async {
try? await Task.sleep(until: ContinuousClock.now + duration, clock: .continuous)
}
90 changes: 90 additions & 0 deletions Samples/Dinner/Sources/Onboarding/Dinner.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift Distributed Tracing open source project
//
// Copyright (c) 2020-2023 Apple Inc. and the Swift Distributed Tracing project
// authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift OpenTelemetry open source project
//
// Copyright (c) 2021 Moritz Lang and the Swift OpenTelemetry project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//


import Tracing

func makeDinner() async throws -> Meal {
try await InstrumentationSystem.tracer.withSpan("makeDinner") { _ in
await sleep(for: .milliseconds(200))

async let veggies = try chopVegetables()
async let meat = marinateMeat()
async let oven = preheatOven(temperature: 350)
// ...
return try await cook(veggies, meat, oven)
}
}

func chopVegetables() async throws -> [Vegetable] {
try await otelChopping1.tracer().withSpan("chopVegetables") { _ in
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know I'm coming in late, but how come this is explicitly referencing otelChopping1?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to mock a multi node trace in one process. I'll make an actual multi process example soon to complement this with more "normal" usage

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, got it. That wasn't explicitly clear when looking at this example what it was actually demonstrating

// Chop the vegetables...!
//
// However, since chopping is a very difficult operation,
// one chopping task can be performed at the same time on a single service!
// (Imagine that... we cannot parallelize these two tasks, and need to involve another service).
async let carrot = try chop(.carrot, tracer: otelChopping1.tracer())
async let potato = try chop(.potato, tracer: otelChopping2.tracer())
return try await [carrot, potato]
}
}

func chop(_ vegetable: Vegetable, tracer: any Tracer) async throws -> Vegetable {
await tracer.withSpan("chop-\(vegetable)") { _ in
await sleep(for: .seconds(5))
// ...
return vegetable // "chopped"
}
}

func marinateMeat() async -> Meat {
await sleep(for: .milliseconds(620))

return await InstrumentationSystem.tracer.withSpan("marinateMeat") { _ in
await sleep(for: .seconds(3))
// ...
return Meat()
}
}

func preheatOven(temperature: Int) async -> Oven {
await InstrumentationSystem.tracer.withSpan("preheatOven") { _ in
// ...
await sleep(for: .seconds(6))
return Oven()
}
}

func cook(_: Any, _: Any, _: Any) async -> Meal {
await InstrumentationSystem.tracer.withSpan("cook") { span in
span.addEvent("children-asking-if-done-already")
await sleep(for: .seconds(3))
span.addEvent("children-asking-if-done-already-again")
await sleep(for: .seconds(2))
// ...
return Meal()
}
}
35 changes: 35 additions & 0 deletions Samples/Dinner/Sources/Onboarding/Model.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift Distributed Tracing open source project
//
// Copyright (c) 2020-2023 Apple Inc. and the Swift Distributed Tracing project
// authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift OpenTelemetry open source project
//
// Copyright (c) 2021 Moritz Lang and the Swift OpenTelemetry project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//


struct Meal: Sendable {}
struct Meat: Sendable {}
struct Oven: Sendable {}
enum Vegetable: Sendable {
case potato
case carrot
}

77 changes: 77 additions & 0 deletions Samples/Dinner/Sources/Onboarding/main.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift Distributed Tracing open source project
//
// Copyright (c) 2020-2023 Apple Inc. and the Swift Distributed Tracing project
// authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift OpenTelemetry open source project
//
// Copyright (c) 2021 Moritz Lang and the Swift OpenTelemetry project authors
Copy link
Member Author

@ktoso ktoso Apr 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Authorship I believe you'd be fine with the samples using this repo's copyright @slashmo ?
I'll change that in a bit

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's fine 👍

// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//


import Logging
import NIO
import OpenTelemetry
import OtlpGRPCSpanExporting
import Tracing

// ==== ----------------------------------------------------------------------------------------------------------------

let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)

LoggingSystem.bootstrap { label in
var handler = StreamLogHandler.standardOutput(label: label)
handler.logLevel = .trace
return handler
}

// ==== ----------------------------------------------------------------------------------------------------------------
// MARK: - Configure OTel

let exporter = OtlpGRPCSpanExporter(config: OtlpGRPCSpanExporter.Config(eventLoopGroup: group))
let processor = OTel.SimpleSpanProcessor(exportingTo: exporter)
let otel = OTel(serviceName: "DinnerService", eventLoopGroup: group, processor: processor)

let otelChopping1 = OTel(serviceName: "ChoppingService-1", eventLoopGroup: group, processor: processor)
let otelChopping2 = OTel(serviceName: "ChoppingService-2", eventLoopGroup: group, processor: processor)

// First start `OTel`, then bootstrap the instrumentation system.
// This makes sure that all components are ready to begin handling spans.
try otel.start().wait()
try otelChopping1.start().wait()
try otelChopping2.start().wait()

// By bootstrapping the instrumentation system, our dependencies
// compatible with "Swift Distributed Tracing" will also automatically
// use the "OpenTelemetry Swift" Tracer 🚀.
InstrumentationSystem.bootstrap(otel.tracer())

// ==== ----------------------------------------------------------------------------------------------------------------
// MARK: - Run the sample app

let dinner = try await makeDinner()

// ==== ----------------------------------------------------------------------------------------------------------------
// MARK: - Shutdown

// Wait a second to let the exporter finish before shutting down.
sleep(2)

try otel.shutdown().wait()
try group.syncShutdownGracefully()
24 changes: 24 additions & 0 deletions Samples/Dinner/docker/collector-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
receivers:
otlp:
protocols:
grpc:
endpoint: otel-collector:4317

exporters:
logging:
verbosity: detailed

jaeger:
endpoint: "jaeger:14250"
tls:
insecure: true

zipkin:
endpoint: "http://zipkin:9411/api/v2/spans"


service:
pipelines:
traces:
receivers: otlp
exporters: [logging, jaeger, zipkin]
26 changes: 26 additions & 0 deletions Samples/Dinner/docker/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
version: '3'
services:
otel-collector:
image: otel/opentelemetry-collector-contrib:latest
command: ["--config=/etc/config.yaml"]
volumes:
- ./collector-config.yaml:/etc/config.yaml
ports:
- "4317:4317"
networks: [exporter]
depends_on: [zipkin, jaeger]

zipkin:
image: openzipkin/zipkin:latest
ports:
- "9411:9411"
networks: [exporter]

jaeger:
image: jaegertracing/all-in-one
ports:
- "16686:16686"
networks: [exporter]

networks:
exporter:
Loading