@@ -26,14 +26,18 @@ get set up with everything you need.
26
26
27
27
### Example Application
28
28
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 ) .
34
34
35
35
Additional examples can be found [ here] ( /docs/languages/erlang/examples/ ) .
36
36
37
+ ### Initial Setup
38
+
39
+ Run ` mix phx.new roll_dice ` . Type "y" to install dependencies.
40
+
37
41
### Dependencies
38
42
39
43
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.
60
64
# mix.exs
61
65
def deps do
62
66
[
67
+ # other default deps...
63
68
{:opentelemetry , " ~> {{% param versions.otelSdk %}}" },
64
69
{:opentelemetry_api , " ~> {{% param versions.otelApi %}}" },
65
70
{:opentelemetry_exporter , " ~> {{% param versions.otelExporter %}}" },
@@ -68,11 +73,12 @@ def deps do
68
73
{:opentelemetry_cowboy , " ~> {{% param versions.otelCowboy %}}" }
69
74
# for Bandit
70
75
{:opentelemetry_bandit , " ~> {{% version-from-registry instrumentation-erlang-bandit %}}" },
76
+ {:opentelemetry_ecto , " ~> {{% param versions.otelEcto %}}" } # if using ecto
71
77
]
72
78
end
73
79
```
74
80
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:
76
82
77
83
``` elixir
78
84
# application.ex
@@ -84,27 +90,32 @@ def start(_type, _args) do
84
90
# or
85
91
OpentelemetryBandit .setup ()
86
92
OpentelemetryPhoenix .setup (adapter: :bandit )
93
+ OpentelemetryEcto .setup ([:dice_game , :repo ]) # if using ecto
87
94
end
88
95
```
89
96
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
+ ```
92
103
93
104
We also need to configure the ` opentelemetry ` application as temporary by adding
94
105
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.
96
107
97
108
``` elixir
98
109
# mix.exs
99
110
def project do
100
111
[
101
- app: :dice_game ,
112
+ app: :roll_dice ,
102
113
version: " 0.1.0" ,
103
114
elixir: " ~> 1.14" ,
104
115
elixirc_paths: elixirc_paths (Mix .env ()),
105
116
start_permanent: Mix .env () == :prod ,
106
117
releases: [
107
- dice_game : [
118
+ roll_dice : [
108
119
applications: [opentelemetry: :temporary ]
109
120
]
110
121
],
@@ -114,20 +125,22 @@ def project do
114
125
end
115
126
```
116
127
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:
125
131
126
132
``` elixir
127
133
# config/dev.exs
128
134
config :opentelemetry , traces_exporter: {:otel_exporter_stdout , []}
129
135
```
130
136
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
+
131
144
If everything went well, you should be able to visit
132
145
[ ` localhost:4000 ` ] ( http://localhost:4000 ) in your browser and see quite a few
133
146
lines that look like this in your terminal.
@@ -157,7 +170,7 @@ fields are.)
157
170
'net.sock.peer.addr' => <<"127.0.0.1">>,
158
171
'http.route' => <<"/">>,'phoenix.action' => home,
159
172
'phoenix.plug' =>
160
- 'Elixir.DiceGameWeb .PageController'}},
173
+ 'Elixir.RollDiceWeb .PageController'}},
161
174
{events,128,128,infinity,0,[]},
162
175
{links,128,128,infinity,0,[]},
163
176
undefined,1,false,
@@ -170,18 +183,54 @@ configure the exporter for your preferred service.
170
183
171
184
### Rolling The Dice
172
185
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
174
187
random number between 1 and 6.
175
188
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
178
220
random number. This seems like a pretty important operation, so in order to
179
221
capture it in our trace we'll need to wrap it in a span.
180
222
181
223
```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
185
234
end
186
235
end
187
236
```
@@ -190,7 +239,7 @@ It would also be nice to know what number it generated, so we can extract it as
190
239
a local variable and add it as an attribute on the span.
191
240
192
241
```elixir
193
- defp dice_roll do
242
+ defp roll_dice do
194
243
Tracer.with_span("dice_roll") do
195
244
roll = Enum.random(1..6)
196
245
@@ -228,7 +277,7 @@ get a random number in response, and 3 spans in your console.
228
277
'net.transport' => 'IP.TCP',
229
278
'http.route' => <<"/api/rolldice">>,
230
279
'phoenix.action' => roll,
231
- 'phoenix.plug' => 'Elixir.DiceGameWeb .DiceController'}},
280
+ 'phoenix.plug' => 'Elixir.RollDiceWeb .DiceController'}},
232
281
{events,128,128,infinity,0,[]},
233
282
{links,128,128,infinity,0,[]},
234
283
undefined,1,false,
0 commit comments