Skip to content

Commit 3db1bd0

Browse files
authored
Merge pull request #1166 from CodingFabian/dash0-example
Added Dash0 example
2 parents 2e0ff10 + 0332a82 commit 3db1bd0

File tree

2 files changed

+177
-0
lines changed

2 files changed

+177
-0
lines changed

docs/examples/dash0/README.md

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
# Dash0 - metrics and traces
2+
3+
In this example, we are going to use [Dash0](https://www.dash0.com) to collect and visualize metrics and traces produced by an application.
4+
We will cover the configuration of OpenTelemetry exporter, as well as the instrumentation of the application using the otel4s library.
5+
6+
Unlike [Jaeger example](../jaeger-docker/README.md), you do not need to set up a collector service locally. The metrics and traces will be sent to a remote Dash0 API.
7+
8+
At the time of writing, Dash0 offers 14 day free trial, afterwards 1 million spans cost 20 cents.
9+
It offers robust analysis and visualization tools that are handy for exploring the world of telemetry.
10+
11+
### Project setup
12+
13+
Configure the project using your favorite tool:
14+
15+
@:select(build-tool)
16+
17+
@:choice(sbt)
18+
19+
Add settings to the `build.sbt`:
20+
```scala
21+
libraryDependencies ++= Seq(
22+
"org.typelevel" %% "otel4s-oteljava" % "@VERSION@", // <1>
23+
"io.opentelemetry" % "opentelemetry-exporter-otlp" % "@OPEN_TELEMETRY_VERSION@" % Runtime, // <2>
24+
"io.opentelemetry" % "opentelemetry-sdk-extension-autoconfigure" % "@OPEN_TELEMETRY_VERSION@" % Runtime // <3>
25+
)
26+
run / fork := true
27+
javaOptions += "-Dotel.java.global-autoconfigure.enabled=true" // <4>
28+
javaOptions += "-Dotel.service.name=dash0-example" // <5>
29+
javaOptions += "-Dotel.exporter.otlp.endpoint=https://ingress.eu-west-1.aws.dash0.com // <6>
30+
```
31+
32+
@:choice(scala-cli)
33+
34+
Add directives to the `tracing.scala`:
35+
```scala
36+
//> using dep "org.typelevel::otel4s-oteljava:@VERSION@" // <1>
37+
//> using dep "io.opentelemetry:opentelemetry-exporter-otlp:@OPEN_TELEMETRY_VERSION@" // <2>
38+
//> using dep "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:@OPEN_TELEMETRY_VERSION@" // <3>
39+
//> using javaOpt "-Dotel.java.global-autoconfigure.enabled=true" // <4>
40+
//> using javaOpt "-Dotel.service.name=dash0-example" // <5>
41+
//> using javaOpt "-Dotel.exporter.otlp.endpoint=https://ingress.eu-west-1.aws.dash0.com" // <6>
42+
```
43+
44+
@:@
45+
46+
1) Add the `otel4s` library
47+
2) Add an OpenTelemetry exporter. Without the exporter, the application will crash
48+
3) Add an OpenTelemetry autoconfigure extension
49+
4) Enable OpenTelemetry SDK autoconfigure mode
50+
5) Add the name of the application to use in the traces
51+
6) Add the Dash0 API endpoint
52+
53+
### OpenTelemetry SDK configuration
54+
55+
As mentioned above, we use `otel.java.global-autoconfigure.enabled` and `otel.service.name` system properties to configure the
56+
OpenTelemetry SDK.
57+
The SDK can be configured via environment variables too. Check the full list
58+
of [environment variable configurations](https://opentelemetry.io/docs/languages/java/configuration)
59+
for more options.
60+
61+
### Acquiring a Dash0 Auth token
62+
63+
First, you must create an account on the [Dash0 website](https://www.dash0.com/sign-up).
64+
Once you have done this, log into your account and navigate to the organization settings page. Under Auth Tokens, you can generate a new auth token.
65+
Under Endpoints you can also discover the value for `-Dotel.exporter.otlp.endpoint` that we used above. It can differ depending on your cloud region choice.
66+
67+
Use a different auth tokens and datasets for test, production, and local development. This organizes your data in Dash0.
68+
69+
### Dash0 configuration
70+
71+
In order to send metrics and traces to Dash0, the auth token and metrics dataset name need to be configured.
72+
Since the auth token is sensitive data, we advise providing them via environment variables:
73+
74+
```shell
75+
$ export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer auth_token,Dash0-Dataset=otel-metrics"
76+
```
77+
78+
1) `Authorization` - the Bearer auth token
79+
2) `Dash0-Dataset` - the name of the dataset to send metrics to.
80+
81+
Each service's traces will land in a dataset defined in 'otel.service.name'.
82+
83+
**Note:** if the `Dash0-Dataset` header is not configured, the **metrics** will be sent to a dataset called `default`.
84+
85+
### Application example
86+
87+
```scala mdoc:silent
88+
import java.util.concurrent.TimeUnit
89+
90+
import cats.effect.{Async, IO, IOApp}
91+
import cats.effect.std.Console
92+
import cats.effect.std.Random
93+
import cats.syntax.all._
94+
import org.typelevel.otel4s.{Attribute, AttributeKey}
95+
import org.typelevel.otel4s.oteljava.OtelJava
96+
import org.typelevel.otel4s.metrics.Histogram
97+
import org.typelevel.otel4s.trace.Tracer
98+
99+
import scala.concurrent.duration._
100+
101+
trait Work[F[_]] {
102+
def doWork: F[Unit]
103+
}
104+
105+
object Work {
106+
def apply[F[_]: Async: Tracer: Console](histogram: Histogram[F, Double]): Work[F] =
107+
new Work[F] {
108+
def doWork: F[Unit] =
109+
Tracer[F].span("Work.DoWork").use { span =>
110+
span.addEvent("Starting the work.") *>
111+
doWorkInternal(steps = 10) *>
112+
span.addEvent("Finished working.")
113+
}
114+
115+
def doWorkInternal(steps: Int): F[Unit] = {
116+
val step = Tracer[F]
117+
.span("internal", Attribute(AttributeKey.long("steps"), steps.toLong))
118+
.surround {
119+
for {
120+
random <- Random.scalaUtilRandom
121+
delay <- random.nextIntBounded(1000)
122+
_ <- Async[F].sleep(delay.millis)
123+
_ <- Console[F].println("Doin' work")
124+
} yield ()
125+
}
126+
127+
val metered = histogram.recordDuration(TimeUnit.MILLISECONDS).surround(step)
128+
129+
if (steps > 0) metered *> doWorkInternal(steps - 1) else metered
130+
}
131+
}
132+
}
133+
134+
object TracingExample extends IOApp.Simple {
135+
def run: IO[Unit] = {
136+
OtelJava
137+
.autoConfigured[IO]()
138+
.evalMap { otel4s =>
139+
otel4s.tracerProvider.get("com.service.runtime")
140+
.flatMap { implicit tracer: Tracer[IO] =>
141+
for {
142+
meter <- otel4s.meterProvider.get("com.service.runtime")
143+
histogram <- meter.histogram[Double]("work.execution.duration").create
144+
_ <- Work[IO](histogram).doWork
145+
} yield ()
146+
}
147+
}
148+
.use_
149+
}
150+
}
151+
```
152+
153+
### Run the application
154+
155+
@:select(build-tool)
156+
157+
@:choice(sbt)
158+
159+
```shell
160+
$ export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer auth_token,Dash0-Dataset=otel-metrics"
161+
$ sbt run
162+
```
163+
164+
@:choice(scala-cli)
165+
166+
```shell
167+
$ export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer auth_token,Dash0-Dataset=otel-metrics"
168+
$ scala-cli run tracing.scala
169+
```
170+
171+
@:@
172+
173+
### Query collected traces and metrics
174+
175+
You can query collected traces and metrics at https://app.dash0.com/.
176+

docs/examples/directory.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ laika.title = Examples
33
laika.navigationOrder = [
44
jaeger-docker
55
honeycomb
6+
dash0
67
grafana
78
]

0 commit comments

Comments
 (0)