Skip to content

Commit 65c06ed

Browse files
authored
[Erlang] RollDice-related doc improvements (#4327)
1 parent 11df7eb commit 65c06ed

File tree

3 files changed

+163
-36
lines changed

3 files changed

+163
-36
lines changed

content/en/docs/languages/erlang/_index.md

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ cascade:
1313
otelExporter: 1.6
1414
otelPhoenix: 1.1
1515
otelCowboy: 0.2
16+
otelEcto: 1.2
1617
---
1718

1819
{{% docs/languages/index-intro erlang %}}

content/en/docs/languages/erlang/exporters.md

+85-8
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,71 @@ collector, which can then export Spans to a self-hosted service like Zipkin or
1616
Jaeger, as well as commercial services. For a full list of available exporters,
1717
see the [registry](/ecosystem/registry/?component=exporter).
1818

19-
For testing purposes the `opentelemetry-erlang` repository has a Collector
20-
configuration,
21-
[config/otel-collector-config.yaml](https://github.com/open-telemetry/opentelemetry-erlang/blob/main/config/otel-collector-config.yaml)
22-
that can be used as a starting point. This configuration is used in
19+
## Setting up the Collector
20+
21+
For testing purposes, you can start with the following Collector configuration
22+
at the root of your project:
23+
24+
```yaml
25+
# otel-collector-config.yaml
26+
27+
# OpenTelemetry Collector config that receives OTLP and exports to Jager
28+
receivers:
29+
otlp:
30+
protocols:
31+
grpc:
32+
endpoint: '0.0.0.0:4317'
33+
http:
34+
endpoint: '0.0.0.0:4318'
35+
processors:
36+
batch:
37+
send_batch_size: 1024
38+
timeout: 5s
39+
exporters:
40+
otlp/jaeger:
41+
endpoint: jaeger-all-in-one:4317
42+
tls:
43+
insecure: true
44+
service:
45+
pipelines:
46+
traces:
47+
receivers: [otlp]
48+
processors: [batch]
49+
exporters: [logging, otlp/jaeger]
50+
```
51+
52+
For a more detailed example, you can view the
53+
[config](https://github.com/open-telemetry/opentelemetry-erlang/blob/main/config/otel-collector-config.yaml)
54+
that `opentelemetry-erlang` uses for testing.
55+
56+
For the purposes of this tutorial, we'll start the Collector as a docker image
57+
along side our app. For this tutorial, we'll continue along with the Dice Roll
58+
example from the [Getting Started](/docs/languages/erlang/getting-started) guide
59+
60+
Add this docker-compose file to the root of your app:
61+
62+
```yaml
63+
# docker-compose.yml
64+
version: '3'
65+
services:
66+
otel:
67+
image: otel/opentelemetry-collector-contrib:0.98.0
68+
command: ['--config=/conf/otel-collector-config.yaml']
69+
ports:
70+
- 4317:4317
71+
- 4318:4318
72+
volumes:
73+
- ./otel-collector-config.yaml:/conf/otel-collector-config.yaml
74+
links:
75+
- jaeger-all-in-one
76+
77+
jaeger-all-in-one:
78+
image: jaegertracing/all-in-one:latest
79+
ports:
80+
- '16686:16686'
81+
```
82+
83+
This configuration is used in
2384
[docker-compose.yml](https://github.com/open-telemetry/opentelemetry-erlang/blob/main/docker-compose.yml)
2485
to start the Collector with receivers for both HTTP and gRPC that then export to
2586
Zipkin also run by [docker-compose](https://docs.docker.com/compose/).
@@ -90,9 +151,12 @@ end
90151
Finally, the runtime configuration of the `opentelemetry` and
91152
`opentelemetry_exporter` Applications are set to export to the Collector. The
92153
configurations below show the defaults that are used if none are set, which are
93-
the HTTP protocol with endpoint of `localhost` on port `4318`. If using `grpc`
94-
for the `otlp_protocol` the endpoint should be changed to
95-
`http://localhost:4317`.
154+
the HTTP protocol with endpoint of `localhost` on port `4318`. Note:
155+
156+
- If using `grpc` for the `otlp_protocol` the endpoint should be changed to
157+
`http://localhost:4317`.
158+
- If you're using the docker compose file from above, you should replace
159+
`localhost` with `otel`.
96160

97161
{{< tabpane text=true >}} {{% tab Erlang %}}
98162

@@ -112,14 +176,27 @@ for the `otlp_protocol` the endpoint should be changed to
112176
{{% /tab %}} {{% tab Elixir %}}
113177

114178
```elixir
115-
# config/runtime.exs
179+
# config/config.exs
116180
config :opentelemetry,
181+
resource: %{service: %{name: "roll_dice_app"}},
117182
span_processor: :batch,
118183
traces_exporter: :otlp
119184
120185
config :opentelemetry_exporter,
121186
otlp_protocol: :http_protobuf,
122187
otlp_endpoint: "http://localhost:4318"
188+
# otlp_endpoint: "http://otel:4318" if using docker compose file
123189
```
124190

125191
{{% /tab %}} {{< /tabpane >}}
192+
193+
You can see your traces by running `docker compose up` in one terminal, then
194+
`mix phx.server` in another. After sending some requests through the app, go to
195+
`http://localhost:16686` and select `roll_dice_app` from the Service drop down,
196+
then click "Find Traces".
197+
198+
## Gotchas
199+
200+
Some environments do not allow containers to execute as root users. If you work
201+
in an environment like this, you can add `user: "1001"` as a top-level key/value
202+
to the `otel` service in the `docker-compose.yml` file used in this tutorial.

content/en/docs/languages/erlang/getting-started.md

+77-28
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,18 @@ get set up with everything you need.
2626

2727
### Example Application
2828

29-
The following example uses a basic [Phoenix](https://www.phoenixframework.org/)
30-
web application. For reference, a complete example of the code you will build
31-
can be found here:
32-
[opentelemetry-erlang-contrib/examples/dice_game](https://github.com/open-telemetry/opentelemetry-erlang-contrib/tree/main/examples/dice_game).
33-
You can git clone that project or just follow along in your browser.
29+
The following example will take you through creating a basic
30+
[Phoenix](https://www.phoenixframework.org/) web application and instrumenting
31+
it with OpenTelemetry. For reference, a complete example of the code you will
32+
build can be found here:
33+
[opentelemetry-erlang-contrib/examples/roll_dice](https://github.com/open-telemetry/opentelemetry-erlang-contrib/tree/main/examples/roll_dice).
3434

3535
Additional examples can be found [here](/docs/languages/erlang/examples/).
3636

37+
### Initial Setup
38+
39+
Run `mix phx.new roll_dice`. Type "y" to install dependencies.
40+
3741
### Dependencies
3842

3943
We'll need a few other dependencies that Phoenix doesn't come with.
@@ -60,6 +64,7 @@ We'll need a few other dependencies that Phoenix doesn't come with.
6064
# mix.exs
6165
def deps do
6266
[
67+
# other default deps...
6368
{:opentelemetry, "~> {{% param versions.otelSdk %}}"},
6469
{:opentelemetry_api, "~> {{% param versions.otelApi %}}"},
6570
{:opentelemetry_exporter, "~> {{% param versions.otelExporter %}}"},
@@ -68,11 +73,12 @@ def deps do
6873
{:opentelemetry_cowboy, "~> {{% param versions.otelCowboy %}}"}
6974
# for Bandit
7075
{:opentelemetry_bandit, "~> {{% version-from-registry instrumentation-erlang-bandit %}}"},
76+
{:opentelemetry_ecto, "~> {{% param versions.otelEcto %}}"} # if using ecto
7177
]
7278
end
7379
```
7480

75-
The last two also need to be setup when your application starts:
81+
The last three also need to be setup when your application starts:
7682

7783
```elixir
7884
# application.ex
@@ -84,27 +90,32 @@ def start(_type, _args) do
8490
# or
8591
OpentelemetryBandit.setup()
8692
OpentelemetryPhoenix.setup(adapter: :bandit)
93+
OpentelemetryEcto.setup([:dice_game, :repo]) # if using ecto
8794
end
8895
```
8996

90-
If you're using ecto, you'll also want to add
91-
`OpentelemetryEcto.setup([:dice_game, :repo])`.
97+
Also, make sure your `endpoint.ex` file contains the following line:
98+
99+
```elixir
100+
# endpoint.ex
101+
plug Plug.Telemetry, event_prefix: [:phoenix, :endpoint]
102+
```
92103

93104
We also need to configure the `opentelemetry` application as temporary by adding
94105
a `releases` section to your project configuration. This will ensure that if it
95-
terminates, even abnormally, the `dice_game` application will be terminated.
106+
terminates, even abnormally, the `roll_dice` application will be terminated.
96107

97108
```elixir
98109
# mix.exs
99110
def project do
100111
[
101-
app: :dice_game,
112+
app: :roll_dice,
102113
version: "0.1.0",
103114
elixir: "~> 1.14",
104115
elixirc_paths: elixirc_paths(Mix.env()),
105116
start_permanent: Mix.env() == :prod,
106117
releases: [
107-
dice_game: [
118+
roll_dice: [
108119
applications: [opentelemetry: :temporary]
109120
]
110121
],
@@ -114,20 +125,22 @@ def project do
114125
end
115126
```
116127

117-
Now we can use the new `mix setup` command to install the dependencies, build
118-
the assets, and create and migrate the database.
119-
120-
### Try It Out
121-
122-
We can ensure everything is working by setting the stdout exporter as
123-
OpenTelemetry's `traces_exporter` and then starting the app with
124-
`mix phx.server`.
128+
The last thing you'll need is to configure the exporter. For development, we can
129+
use the stdout exporter to ensure everything is working properly. Configure
130+
OpenTelemetry's `traces_exporter` like so:
125131

126132
```elixir
127133
# config/dev.exs
128134
config :opentelemetry, traces_exporter: {:otel_exporter_stdout, []}
129135
```
130136

137+
Now we can use the new `mix setup` command to install the dependencies, build
138+
the assets, and create and migrate the database.
139+
140+
### Try It Out
141+
142+
Run `mix phx.server`.
143+
131144
If everything went well, you should be able to visit
132145
[`localhost:4000`](http://localhost:4000) in your browser and see quite a few
133146
lines that look like this in your terminal.
@@ -157,7 +170,7 @@ fields are.)
157170
'net.sock.peer.addr' => <<"127.0.0.1">>,
158171
'http.route' => <<"/">>,'phoenix.action' => home,
159172
'phoenix.plug' =>
160-
'Elixir.DiceGameWeb.PageController'}},
173+
'Elixir.RollDiceWeb.PageController'}},
161174
{events,128,128,infinity,0,[]},
162175
{links,128,128,infinity,0,[]},
163176
undefined,1,false,
@@ -170,18 +183,54 @@ configure the exporter for your preferred service.
170183
171184
### Rolling The Dice
172185
173-
Now we'll check out the API endpoint that will let us roll the dice and return a
186+
Now we'll create the API endpoint that will let us roll the dice and return a
174187
random number between 1 and 6.
175188
176-
Before we call our API, let's add our first bit of manual instrumentation. In
177-
our `DiceController` we call a private `dice_roll` method that generates our
189+
```elixir
190+
# router.ex
191+
scope "/api", RollDiceWeb do
192+
pipe_through :api
193+
194+
get "/rolldice", DiceController, :roll
195+
end
196+
```
197+
198+
And create a bare `DiceController` without any instrumentation:
199+
200+
```elixir
201+
# lib/roll_dice_web/controllers/dice_controller.ex
202+
defmodule RollDiceWeb.DiceController do
203+
use RollDiceWeb, :controller
204+
205+
def roll(conn, _params) do
206+
send_resp(conn, 200, roll_dice())
207+
end
208+
209+
defp roll_dice do
210+
to_string(Enum.random(1..6))
211+
end
212+
end
213+
```
214+
215+
If you like, call the route to see the result. You'll still see some telemetry
216+
pop up in your terminal. Now it's time to enrich that telemetry by instrumenting
217+
our `roll` function by hand
218+
219+
In our `DiceController` we call a private `dice_roll` method that generates our
178220
random number. This seems like a pretty important operation, so in order to
179221
capture it in our trace we'll need to wrap it in a span.
180222
181223
```elixir
182-
defp dice_roll do
183-
Tracer.with_span("dice_roll") do
184-
to_string(Enum.random(1..6))
224+
defmodule RollDiceWeb.DiceController do
225+
use RollDiceWeb, :controller
226+
require OpenTelemetry.Tracer, as: Tracer
227+
228+
# ...snip
229+
230+
defp roll_dice do
231+
Tracer.with_span("dice_roll") do
232+
to_string(Enum.random(1..6))
233+
end
185234
end
186235
end
187236
```
@@ -190,7 +239,7 @@ It would also be nice to know what number it generated, so we can extract it as
190239
a local variable and add it as an attribute on the span.
191240
192241
```elixir
193-
defp dice_roll do
242+
defp roll_dice do
194243
Tracer.with_span("dice_roll") do
195244
roll = Enum.random(1..6)
196245
@@ -228,7 +277,7 @@ get a random number in response, and 3 spans in your console.
228277
'net.transport' => 'IP.TCP',
229278
'http.route' => <<"/api/rolldice">>,
230279
'phoenix.action' => roll,
231-
'phoenix.plug' => 'Elixir.DiceGameWeb.DiceController'}},
280+
'phoenix.plug' => 'Elixir.RollDiceWeb.DiceController'}},
232281
{events,128,128,infinity,0,[]},
233282
{links,128,128,infinity,0,[]},
234283
undefined,1,false,

0 commit comments

Comments
 (0)