Skip to content

Commit c0761d2

Browse files
author
Ignacio Bonafonte
authored
Merge pull request #228 from vvydier/otlp-example
OTLP Exporter example to send traces and metrics This example uses the OTLP Exporter to send traces and metrics to otel-collector which is configured to export traces to zipkin and metrics to prometheus respectively
2 parents 426742c + 3080a66 commit c0761d2

File tree

9 files changed

+240
-0
lines changed

9 files changed

+240
-0
lines changed

Examples/OTLP Exporter/README.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
### OTLP Exporter Example
2+
3+
This example shows how to use [OTLP Exporter](https://github.com/open-telemetry/opentelemetry-swift/tree/main/Sources/Exporters/OpenTelemetryProtocol) to instrument a simple Swift application.
4+
5+
This example will export spans data simultaneously using [OTLP Exporter ](https://github.com/open-telemetry/opentelemetry-swift/tree/main/Sources/Exporters/OpenTelemetryProtocol) and grpc. It will use [proto format](https://github.com/open-telemetry/opentelemetry-proto).
6+
7+
8+
## Run the Application
9+
10+
1. Run docker: This will start otel-collector, Zipkin and Prometheus
11+
12+
```shell script
13+
# from this directory
14+
docker-compose up
15+
```
16+
17+
2. Run app
18+
19+
```shell script
20+
# from this directory
21+
swift run OTLPExporter
22+
```
23+
24+
3. Teardown the docker images
25+
26+
```shell script
27+
# from this directory
28+
docker-compose down
29+
```
30+
31+
4. Open page at <http://localhost:9411/zipkin/> - you should be able to see the spans in zipkin
32+
![Screenshot of the running example](images/zipkin-spans.png)
33+
34+
### Prometheus UI
35+
36+
The prometheus client will be available at <http://localhost:9090>.
37+
38+
Note: It may take some time for the application metrics to appear on the Prometheus dashboard.
39+
![Screenshot of the running example](images/prometheus-metrics.png)
40+
41+
## Useful links
42+
43+
- For more information on OpenTelemetry, visit: <https://opentelemetry.io/>
44+
- For more information on trace, visit: <https://github.com/open-telemetry/opentelemetry-swift/tree/main/Sources/OpenTelemetrySdk/Trace>
45+
- For more information on metrics, visit: <https://github.com/open-telemetry/opentelemetry-swift/tree/main/Sources/OpenTelemetrySdk/Metrics>
46+
47+
## LICENSE
48+
49+
Apache License 2.0
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
receivers:
2+
otlp:
3+
protocols:
4+
grpc:
5+
http:
6+
cors_allowed_origins:
7+
- http://*
8+
- https://*
9+
10+
exporters:
11+
logging:
12+
loglevel: debug
13+
zipkin:
14+
endpoint: "http://zipkin-all-in-one:9411/api/v2/spans"
15+
prometheus:
16+
endpoint: "0.0.0.0:9464"
17+
18+
processors:
19+
resource:
20+
attributes:
21+
- key: service.name
22+
value: OTLP Exporter
23+
action: insert
24+
batch:
25+
26+
service:
27+
pipelines:
28+
traces:
29+
receivers: [otlp]
30+
exporters: [zipkin, logging]
31+
processors: [resource, batch]
32+
metrics:
33+
receivers: [otlp]
34+
exporters: [prometheus]
35+
processors: [resource, batch]
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
version: "3"
2+
services:
3+
# Collector
4+
collector:
5+
image: otel/opentelemetry-collector:0.25.0
6+
# image: otel/opentelemetry-collector:latest
7+
command: ["--config=/conf/collector-config.yaml", "--log-level=DEBUG"]
8+
volumes:
9+
- ./collector-config.yaml:/conf/collector-config.yaml
10+
ports:
11+
- "9464:9464"
12+
- "4317:4317"
13+
- "55681:55681"
14+
depends_on:
15+
- zipkin-all-in-one
16+
17+
# Zipkin
18+
zipkin-all-in-one:
19+
image: openzipkin/zipkin:latest
20+
ports:
21+
- "9411:9411"
22+
23+
# Prometheus
24+
prometheus:
25+
container_name: prometheus
26+
image: prom/prometheus:latest
27+
volumes:
28+
- ./prometheus.yaml:/etc/prometheus/prometheus.yml
29+
ports:
30+
- "9090:9090"
31+
# - "9184:9184"
472 KB
Loading
567 KB
Loading

Examples/OTLP Exporter/main.swift

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import Foundation
7+
import OpenTelemetryProtocolExporter
8+
import OpenTelemetryApi
9+
import OpenTelemetrySdk
10+
import ResourceExtension
11+
import StdoutExporter
12+
import ZipkinExporter
13+
import SignPostIntegration
14+
import GRPC
15+
import NIO
16+
import NIOSSL
17+
18+
let sampleKey = "sampleKey"
19+
let sampleValue = "sampleValue"
20+
21+
var resources = DefaultResources().get()
22+
23+
let instrumentationLibraryName = "OTLPExporter"
24+
let instrumentationLibraryVersion = "semver:0.1.0"
25+
var instrumentationLibraryInfo = InstrumentationLibraryInfo(name: instrumentationLibraryName, version: instrumentationLibraryVersion)
26+
27+
var tracer: TracerSdk
28+
tracer = OpenTelemetrySDK.instance.tracerProvider.get(instrumentationName: instrumentationLibraryName, instrumentationVersion: instrumentationLibraryVersion) as! TracerSdk
29+
30+
let configuration = ClientConnection.Configuration(
31+
target: .hostAndPort("localhost", 4317),
32+
eventLoopGroup: MultiThreadedEventLoopGroup(numberOfThreads: 1)
33+
)
34+
let client = ClientConnection(configuration: configuration)
35+
36+
let otlpTraceExporter = OtlpTraceExporter(channel: client)
37+
let stdoutExporter = StdoutExporter()
38+
let spanExporter = MultiSpanExporter(spanExporters: [otlpTraceExporter, stdoutExporter])
39+
40+
let spanProcessor = SimpleSpanProcessor(spanExporter: spanExporter)
41+
OpenTelemetrySDK.instance.tracerProvider.addSpanProcessor(spanProcessor)
42+
43+
if #available(macOS 10.14, *) {
44+
OpenTelemetrySDK.instance.tracerProvider.addSpanProcessor(SignPostIntegration())
45+
}
46+
47+
func createSpans() {
48+
let parentSpan1 = tracer.spanBuilder(spanName: "Main").setSpanKind(spanKind: .client).startSpan()
49+
parentSpan1.setAttribute(key: sampleKey, value: sampleValue)
50+
OpenTelemetry.instance.contextProvider.setActiveSpan(parentSpan1)
51+
for _ in 1...3 {
52+
doWork()
53+
}
54+
Thread.sleep(forTimeInterval: 0.5)
55+
56+
let parentSpan2 = tracer.spanBuilder(spanName: "Another").setSpanKind(spanKind: .client).startSpan()
57+
parentSpan2.setAttribute(key: sampleKey, value: sampleValue)
58+
OpenTelemetry.instance.contextProvider.setActiveSpan(parentSpan2)
59+
// do more Work
60+
for _ in 1...3 {
61+
doWork()
62+
}
63+
Thread.sleep(forTimeInterval: 0.5)
64+
65+
parentSpan2.end()
66+
parentSpan1.end()
67+
}
68+
69+
func doWork() {
70+
let childSpan = tracer.spanBuilder(spanName: "doWork").setSpanKind(spanKind: .client).startSpan()
71+
childSpan.setAttribute(key: sampleKey, value: sampleValue)
72+
Thread.sleep(forTimeInterval: Double.random(in: 0..<10)/100)
73+
childSpan.end()
74+
}
75+
76+
// Create a Parent span (Main) and do some Work (child Spans). Repeat for another Span.
77+
createSpans()
78+
79+
//Metrics
80+
let otlpMetricExporter = OtlpMetricExporter(channel: client)
81+
let processor = MetricProcessorSdk()
82+
let meterProvider = MeterProviderSdk(metricProcessor: processor, metricExporter: otlpMetricExporter, metricPushInterval: 0.1)
83+
84+
var meter = meterProvider.get(instrumentationName: "otlp_example_meter'")
85+
var exampleCounter = meter.createIntCounter(name: "otlp_example_counter")
86+
var exampleMeasure = meter.createIntMeasure(name: "otlp_example_measure")
87+
var exampleObserver = meter.createIntObserver(name: "otlp_example_observation") { observer in
88+
var taskInfo = mach_task_basic_info()
89+
var count = mach_msg_type_number_t(MemoryLayout<mach_task_basic_info>.size) / 4
90+
let _: kern_return_t = withUnsafeMutablePointer(to: &taskInfo) {
91+
$0.withMemoryRebound(to: integer_t.self, capacity: 1) {
92+
task_info(mach_task_self_, task_flavor_t(MACH_TASK_BASIC_INFO), $0, &count)
93+
}
94+
}
95+
labels1 = ["dim1": "value1"]
96+
observer.observe(value: Int(taskInfo.resident_size), labels: labels1)
97+
}
98+
99+
var labels1 = ["dim1": "value1"]
100+
for _ in 1...3000 {
101+
exampleCounter.add(value: 1, labelset: meter.getLabelSet(labels: labels1))
102+
exampleMeasure.record(value: 100, labelset: meter.getLabelSet(labels: labels1))
103+
exampleMeasure.record(value: 500, labelset: meter.getLabelSet(labels: labels1))
104+
exampleMeasure.record(value: 5, labelset: meter.getLabelSet(labels: labels1))
105+
exampleMeasure.record(value: 750, labelset: meter.getLabelSet(labels: labels1))
106+
sleep(1)
107+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
global:
2+
scrape_interval: 15s # Default is every 1 minute.
3+
4+
scrape_configs:
5+
- job_name: 'collector'
6+
# metrics_path defaults to '/metrics'
7+
# scheme defaults to 'http'.
8+
static_configs:
9+
- targets: ['collector:9464']

Package.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ let package = Package(
4141
.library(name: "NetworkStatus", type: .static, targets: ["NetworkStatus"]),
4242
.library(name: "libNetworkStatus", type: .static, targets: ["NetworkStatus"]),
4343
.executable(name: "simpleExporter", targets: ["SimpleExporter"]),
44+
.executable(name: "OTLPExporter", targets: ["OTLPExporter"]),
4445
.executable(name: "loggingTracer", targets: ["LoggingTracer"]),
4546
],
4647
dependencies: [
@@ -165,6 +166,10 @@ let package = Package(
165166
dependencies: ["OpenTelemetrySdk", "JaegerExporter", "StdoutExporter", "ZipkinExporter", "ResourceExtension", "SignPostIntegration"],
166167
path: "Examples/Simple Exporter",
167168
exclude: ["README.md"]),
169+
.target(name: "OTLPExporter",
170+
dependencies: ["OpenTelemetrySdk", "OpenTelemetryProtocolExporter", "StdoutExporter", "ZipkinExporter", "ResourceExtension", "SignPostIntegration"],
171+
path: "Examples/OTLP Exporter",
172+
exclude: ["README.md"]),
168173
.target(name: "PrometheusSample",
169174
dependencies: ["OpenTelemetrySdk", "PrometheusExporter"],
170175
path: "Examples/Prometheus Sample",

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,11 @@ Implemented metrics exporters: Prometheus, Datadog, and OpenTelemetry collector
5353

5454
The package includes some example projects with basic functionality:
5555

56+
- `Datadog Sample` - Shows the Datadog exporter used with a Simple Exporter, showing how to configure for sending.
5657
- `Logging Tracer` - Simple api implementation of a Tracer that logs every api call
58+
- `Network Tracer` - Shows how to use the `URLSessionInstrumentation` instrumentation in your application
5759
- `Simple Exporter` - Shows the Jaeger an Stdout exporters in action using a MultiSpanExporter. Can be easily modified for other exporters
5860
- `Prometheus Sample` - Shows the Prometheus exporter reporting metrics to a Prometheus instance
61+
- `OTLP Exporter` - Shows the OTLP exporter reporting traces to Zipkin and metrics to a Prometheus via the otel-collector
62+
5963

0 commit comments

Comments
 (0)